#ifndef __NET_H__
#define __NET_H__
#include "types.h"


#define PKTSIZE			1518
#define PKTSIZE_ALIGN		1536
#define PKTALIGN	32

#define PROT_IP		0x0800		/* IP protocol			*/
#define PROT_ARP	0x0806		/* IP ARP protocol		*/
#define PROT_RARP	0x8035		/* IP ARP protocol		*/

#define PKTBUFSRX	4

extern int		NetState;		/* Network loop state		*/
#define NETLOOP_CONTINUE	1
#define NETLOOP_RESTART		2
#define NETLOOP_SUCCESS		3
#define NETLOOP_FAIL		4

#define VLAN_NONE	4095			/* untagged 			*/

#define PROT_IP		0x0800		/* IP protocol			*/
#define PROT_ARP	0x0806		/* IP ARP protocol		*/
#define PROT_RARP	0x8035		/* IP ARP protocol		*/
#define PROT_VLAN	0x8100		/* IEEE 802.1q protocol		*/

#define IPPROTO_ICMP	 1	/* Internet Control Message Protocol	*/
#define IPPROTO_UDP	17	/* User Datagram Protocol		*/

#define ARP_HDR_SIZE	(8+20)		/* Size assuming ethernet	*/

typedef enum { ARP, TFTP, PING } proto_t;
typedef ulong		IPaddr_t;

typedef struct
{
	ushort		ar_hrd;		/* Format of hardware address	*/
#   define ARP_ETHER	    1		/* Ethernet  hardware address	*/
	ushort		ar_pro;		/* Format of protocol address	*/
	uchar		ar_hln;		/* Length of hardware address	*/
	uchar		ar_pln;		/* Length of protocol address	*/
	ushort		ar_op;		/* Operation			*/
#   define ARPOP_REQUEST    1		/* Request  to resolve  address	*/
#   define ARPOP_REPLY	    2		/* Response to previous request	*/

#   define RARPOP_REQUEST   3		/* Request  to resolve  address	*/
#   define RARPOP_REPLY	    4		/* Response to previous request */

	/*
	 * The remaining fields are variable in size, according to
	 * the sizes above, and are defined as appropriate for
	 * specific hardware/protocol combinations.
	 */
	uchar		ar_data[0];
} ARP_t;

#define ICMP_ECHO_REPLY		0	/* Echo reply 			*/
#define ICMP_REDIRECT		5	/* Redirect (change route)	*/
#define ICMP_ECHO_REQUEST	8	/* Echo request			*/

typedef struct icmphdr {
	uchar		type;
	uchar		code;
	ushort		checksum;
	union {
		struct {
			ushort	id;
			ushort	sequence;
		} echo;
		ulong	gateway;
		struct {
			ushort	__unused;
			ushort	mtu;
		} frag;
	} un;
} ICMP_t;

typedef void	thand_f(void);
typedef void	rxhand_f(uchar *, unsigned, unsigned, unsigned);

typedef struct {
	uchar		et_dest[6];	/* Destination node		*/
	uchar		et_src[6];	/* Source node			*/
	ushort		et_protlen;	/* Protocol or length		*/
	uchar		et_dsap;	/* 802 DSAP			*/
	uchar		et_ssap;	/* 802 SSAP			*/
	uchar		et_ctl;		/* 802 control			*/
	uchar		et_snap1;	/* SNAP				*/
	uchar		et_snap2;
	uchar		et_snap3;
	ushort		et_prot;	/* 802 protocol			*/
} Ethernet_t;

#define ETHER_HDR_SIZE	14		/* Ethernet header size		*/
#define E802_HDR_SIZE	22		/* 802 ethernet header size	*/


typedef struct {
	uchar		ip_hl_v;	/* header length and version	*/
	uchar		ip_tos;		/* type of service		*/
	ushort		ip_len;		/* total length			*/
	ushort		ip_id;		/* identification		*/
	ushort		ip_off;		/* fragment offset field	*/
	uchar		ip_ttl;		/* time to live			*/
	uchar		ip_p;		/* protocol			*/
	ushort		ip_sum;		/* checksum			*/
	IPaddr_t	ip_src;		/* Source IP address		*/
	IPaddr_t	ip_dst;		/* Destination IP address	*/
	ushort		udp_src;	/* UDP source port		*/
	ushort		udp_dst;	/* UDP destination port		*/
	ushort		udp_len;	/* Length of UDP packet		*/
	ushort		udp_xsum;	/* Checksum			*/
} IP_t;
#define IP_HDR_SIZE_NO_UDP	(sizeof (IP_t) - 8)
#define IP_HDR_SIZE		(sizeof (IP_t))


extern volatile uchar	PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];

extern volatile uchar *NetTxPacket;

extern volatile uchar *NetRxPackets[PKTBUFSRX];
extern volatile uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets			*/
extern volatile uchar *NetRxPkt;
extern int NetRxPktLen;		/* Current rx packet length		*/

extern IPaddr_t NetOurIP;	
extern IPaddr_t	NetOurSubnetMask;
extern uchar NetOurEther[6];		/* Our ethernet address			*/

extern uchar NetBcastAddr[6];
extern uchar NetEtherNullAddr[6];

extern unsigned	NetIPID;		/* IP packet ID				*/
extern int NetState;		/* Network loop state			*/

unsigned NetCksum(uchar * ptr, int len);
void NetReceive(volatile uchar * inpkt, int len);
IPaddr_t string_to_ip(const char *s);
//unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base);
unsigned long simple_strtoul(char **p);
int NetSetEther(volatile uchar * xet, uchar * addr, uint prot);
void NetSetIP(volatile uchar * xip, IPaddr_t dest,
    int dport, int sport, int len);
int	NetLoop(proto_t);
void NetSetHandler(rxhand_f * f);
int NetEthHdrSize(void);
inline IPaddr_t NetReadIP(void *from);
inline void NetWriteIP(void *to, IPaddr_t ip);
inline void NetCopyIP(void *to, void *from);

/* arp */
void ArpRequest (void);
extern IPaddr_t	NetArpWaitPacketIP;
extern uchar  *NetArpWaitPacketMAC;
extern IPaddr_t	NetArpWaitReplyIP;
extern int NetArpWaitTxPacketSize;
extern uchar *NetArpWaitTxPacket;
extern uchar 		NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
extern int		NetArpWaitTry;

/* ping */
void PingStart(void);
extern IPaddr_t	NetPingIP;

/* tftp */
void TftpStart (void);
extern IPaddr_t	NetServerIP;
extern ulong NetBootFileXferSize;


#endif /* __NET_H__ */
